package br.ufpb.di.ppgi.persistencia.transaction;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.ufpb.di.ppgi.persistencia.domainstore.DomainStore;

@Intercepts
public class TransactionInterceptor implements Interceptor {
	private static final Logger LOGGER = LoggerFactory.getLogger(TransactionInterceptor.class);
	private static void debug(String format, Object ... args) {
		if (LOGGER.isDebugEnabled())
			LOGGER.debug(String.format(format, args));
	}

	private final DomainStore domain;
	
	public TransactionInterceptor(DomainStore domain) {
		this.domain = domain;
	}
	
	public boolean accepts(ResourceMethod rMethod) {
		boolean accepts =  
			rMethod
				.getMethod()
				.isAnnotationPresent(TransactionScoped.class)
			||
			rMethod
				.getResource()
				.getType()
				.isAnnotationPresent(TransactionScoped.class);
		if (accepts) debug("[ThreadID %d] @TransactionScoped annotation found to current logic",Thread.currentThread().getId());
		return accepts;
	}

	public void intercept(InterceptorStack stack, ResourceMethod method,
			Object instance) throws InterceptionException {
		final long threadId = Thread.currentThread().getId();
		try {
			
			debug("[ThreadID %d] Iniciando Transação",threadId);
			domain.beginTransaction();
			debug("[ThreadID %d] Transação iniciada",threadId);
			stack.next(method, instance);
			if (domain.isTrasactionActive()) {
				debug("[ThreadID %d] Confirmando transação",threadId);
				domain.commit();
				debug("[ThreadID %d] Transação confirmada",threadId);
			} else
				LOGGER.warn("[ThreadID %d] Transação já estava comitada, antes do interceptor executar o commit.");
			
		} finally {
			if (domain.isTrasactionActive()) {
				LOGGER.error("[ThreadID %d] falha ao confirmar tranzação revertendo tranzação", threadId);
				domain.rollback();
				debug("[ThreadID %d] Tranzação revertida.", threadId);
			}
		}
	}
}
